/* ================================================= */
/* parser pour l'analyse syntaxique d'un fichier BPI */
/* author Mathieu Barbin                             */
/* version 1.0.*                                     */
/* ================================================= */

%{
  open Message
  open Inputtools
%}

%token DEFINE
%token SYSARGV
%token STRINGARGV
%token INPUT
%token SOURCE
%token INIT
%token SETCPS
%token DWHERE
%token WHERE
%token DEND

%token TEXT
%token FILE
%token BINARYFILE
%token COUNTER
%token UNITFUN
%token ARGFUN

%token LEX_LOG
%token LEX_MOD
%token LEX_MIN
%token LEX_MAX
%token LEX_ADD
%token LEX_SUB
%token LEX_MULT
%token LEX_DIV
%token LEX_EXP
%token LPAREN
%token RPAREN
%token EGAL
%token POINTPOINT
%token VIRG
%token POINT_VIRG
%token DEUX_POINTS
%token LCROCHET
%token RCROCHET
%token LACC
%token RACC
%token <int> INT
%token <string> IDENT
%token <string> STRING
%token <string> CODE
%token <string> CODE01
%token EOF

// le fichier BPI contient :
// 1 - #source = le langage utilis?? pour les fonctions perso (default "ocaml")
// 2 - #setCPS int = le nombre d'entr??es maxiales chaque seconde
// 3 - #define ou #sysargv (facultatif)
// 4 - #init (facultatif)
// 5 - #input interface #where ... #end where

%type <string * int option * (Inputtools.macro_BP list) * (int * string) * Inputtools.bpi_interface * ((int * Inputtools.description_entree) list)> input

%start input

%%

input:
  | source_declaration setCPS macro_define_list init_possible interface descriptions{($1,$2,$3,$4,$5,$6)}
;

setCPS:
  |              { None }
  | SETCPS INT   { Some $2 }
;

source_declaration:
  | SOURCE EGAL STRING { $3 }
  |                    { "ocaml" }
;

init_possible:
  |            { (!index_ligne_bpi_file, "") }
  | INIT CODE  { (!index_ligne_bpi_file, $2) }
;

macro_define_list:
  |   { [] }
  | DEFINE IDENT expr_arith macro_define_list                        
      { (MacDefine 
	   {
	     fichier_macro = message#get_bpi_file;
	     ligne_macro = !index_ligne_bpi_file; 
	     nom_macro = $2; 
	     corps_macro = DefInt $3
	   })::($4) 
      }
  | DEFINE IDENT STRING macro_define_list                        
      { (MacDefine 
	   {
	     fichier_macro = message#get_bpi_file;
	     ligne_macro = !index_ligne_bpi_file; 
	     nom_macro = $2; 
	     corps_macro = DefString $3
	   })::($4) 
      } 
  | SYSARGV IDENT macro_define_list
      { (MacIntArg (!index_ligne_bpi_file, $2))::($3)
      }
  | STRINGARGV IDENT macro_define_list
      { (MacStringArg (!index_ligne_bpi_file, $2))::($3)
      }
;

interface:
  | INPUT IDENT EGAL variables_list { InputExt ($2, $4) }
  | INPUT variables_list            { InputExt ("input", $2) }

;

descriptions:
  | DWHERE descriptions_list DEND WHERE  { $2 }
;

descriptions_list:
  |                                   { [] }
  | une_description descriptions_list { $1::$2 } 
;

une_description:
  | variables_list EGAL text_or_file POINT_VIRG     { (!index_ligne_bpi_file , { input_net_vars = $1;
							type_des = $3}) }
;

text_or_file:
  | TEXT CODE01                                     { Text $2 }
  | FILE LPAREN STRING RPAREN                       { File $3 }
  | BINARYFILE LPAREN STRING RPAREN	            { BinaryFile $3 }
  | ARGFUN LPAREN STRING RPAREN                     { ArgFun (!index_ligne_bpi_file, $3) }
  | UNITFUN LPAREN STRING RPAREN                    { UnitFun (!index_ligne_bpi_file, $3) }
  | COUNTER                                         { Counter }
;


variables_list:
    LPAREN arguments RPAREN                            { $2 }
  | arguments                                          { $1 }
; 

arguments:
  |                                                    { [] }
  | argument                                           { [$1] }
  | argument VIRG arguments                            { $1::$3 }
;
 
argument:
  | IDENT                                              { Simple $1 }
  | IDENT indexation_list                              { Vecteur (!index_ligne_bpo_file,
								  $1,$2) }
;

indexation_list:
  | indexation                                         { [$1] }
  | indexation indexation_list                         { $1::$2 }
;

indexation:
  | DEUX_POINTS LCROCHET expr_arith RCROCHET           { SegmentInit $3 }
  | LCROCHET expr_arith POINTPOINT expr_arith RCROCHET { Intervalle ($2, $4) }
  | LCROCHET expr_arith RCROCHET                       { Index $2 }
;
 
// LES EXPRESSIONS ARITHMETIQUES 

expr_arith:
  | expr_arith LEX_ADD expr_arith_close    { ADD ($1, $3) }
  | expr_arith LEX_SUB expr_arith_close    { SUB ($1, $3) }
  | LEX_SUB expr_arith_close               { SUB (CST 0, $2) }
  | expr_arith_close                       { $1 }
;

expr_arith_close:
  | expr_arith_close LEX_DIV expr_prio     { DIV ($1, $3) }
  | expr_arith_close LEX_MULT expr_prio    { MULT ($1, $3) }
  | expr_arith_close LEX_MOD expr_prio     { MOD ($1, $3) }
  | expr_prio                              { $1 }
;

expr_prio:
  | expr_prio LEX_EXP expr_terminale       { EXP ($1, $3) }
  | LEX_LOG expr_terminale                 { LOG $2 }
  | expr_terminale                         { $1 }
                               
expr_terminale:
  | INT                                                  { CST $1 }
  | IDENT                                                { VAR $1 }
  | LPAREN expr_arith RPAREN                             { $2 }
  | LEX_MAX LPAREN expr_arith VIRG expr_arith RPAREN     { MAX ($3, $5) }
  | LEX_MIN LPAREN expr_arith VIRG expr_arith RPAREN     { MIN ($3, $5) } 
;
